package apis

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-admin-team/go-admin-core/sdk/api"
	"net/http"
	"regexp"
	"strconv"
	"time"
	"tuowei.com/app/admin/models"
	dto2 "tuowei.com/app/admin/service/dto"
	"tuowei.com/app/teacher/service"
	"tuowei.com/app/teacher/service/dto"
	"tuowei.com/app/teacher/service/response"
	Beans "tuowei.com/pkg/sing/beans"
	HttpHelper "tuowei.com/pkg/sing/http_utils"
	"tuowei.com/pkg/util"
	"tuowei.com/pkg/xlog"
)

type Order struct {
	api.Api
	base
}

func (o Order) FollowUnpaidOrder(ctx *gin.Context) {
	teacher := o.GetTeacherInfo(ctx)
	s := service.Order{}
	req := dto.FollowUnpaidOrder{}
	if err := o.MakeContext(ctx).MakeOrm().MakeService(&s.Service).
		Bind(&req, binding.JSON).Errors; err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	detail := models.OfflineOrder{}
	err := o.Orm.Where("id = ?", req.Id).First(&detail).Error
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	if detail.Status != models.OfflineStatusFollowIng {
		o.Error(http.StatusInternalServerError, errors.New("当前订单状态不是待跟进状态"), "当前订单状态不是待跟进状态")
		return
	}
	// 直接状态变成完成状态
	detail.Status = models.OfflineStatusComplete
	err = o.Orm.Updates(&detail).Error
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	// 变更学生去向
	o.Orm.Table(models.SysStudent{}.TableName()).Where("id = ?", detail.BuyerId).Update("follow_direction", req.FollowDirection)
	// 写入记录表
	record := models.OfflineOrderProgress{}
	record.Creator = teacher.SysUser.Username
	record.Status = models.OfflineStatusComplete //变更到财务复审状态
	record.OrderId = req.Id
	record.OperateTime = time.Now()
	record.FollowUp = req.FollowUp
	o.Orm.Save(&record)
	o.OK(nil, "success")
}

func (o Order) FollowPaidOrder(ctx *gin.Context) {
	teacher := o.GetTeacherInfo(ctx)
	s := service.Order{}
	req := dto.FollowPayedOrder{}
	if err := o.MakeContext(ctx).MakeOrm().MakeService(&s.Service).
		Bind(&req, binding.JSON).Errors; err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	if req.IdCard != "" {
		ruler := "(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)"
		reg := regexp.MustCompile(ruler)
		if !reg.MatchString(req.IdCard) {
			o.Error(http.StatusInternalServerError, errors.New("身份证号码格式不正确"), "身份证号码格式不正确")
			return
		}
	}
	detail := models.OfflineOrder{}
	err := o.Orm.Where("id = ?", req.Id).Preload("Course").Preload("Customer").First(&detail).Error
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	if detail.Customer == nil {
		o.Error(http.StatusInternalServerError, nil, "订单错误:没有对应的学生")
		return
	}
	if len(detail.Course) <= 0 {
		o.Error(http.StatusInternalServerError, nil, "订单错误:没有对应的课程")
		return
	}
	if detail.Status != models.OfflineStatusFollowIng {
		o.Error(http.StatusInternalServerError, errors.New("当前订单状态不是待跟进状态"), "当前订单状态不是待跟进状态")
		return
	}
	if detail.SignFlowId == "" {
		o.Error(http.StatusInternalServerError, nil, "学生尚未发起签字流程")
		return
	}
	// 看是否已经签过合同了,如果未签字，则查询一次接口
	if detail.Signed == 0 {
		url := fmt.Sprintf("/v3/sign-flow/%s/detail", detail.SignFlowId)
		bts, httpStatusCode := HttpHelper.SendCommHttp(url, "", http.MethodGet)
		if httpStatusCode != http.StatusOK {
			o.Error(http.StatusInternalServerError, nil, "请求e签查询签署流程失败,状态:"+strconv.Itoa(httpStatusCode))
			return
		}
		rsp := Beans.SignDetailRsp{}
		err = json.Unmarshal(bts, &rsp)
		if err != nil {
			o.Error(http.StatusInternalServerError, err, err.Error())
			return
		}
		if rsp.Code != 0 {
			o.Error(http.StatusInternalServerError, nil, rsp.Message)
			return
		}
		if rsp.Data.SignFlowStatus != 2 {
			o.Error(http.StatusInternalServerError, nil, "学生尚未签字，原因："+rsp.Data.SignFlowDescription)
			return
		}
	}
	// 如果没有签字没有电子合同，则需要重新高搞一份
	var contractNumber string
	n, err := models.Contract{}.GetMaxContractNumAndInsert(o.Orm, detail.Customer.Province, time.Now().Format("2006"))
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	contractNumber = fmt.Sprintf("%02d%s%05d", detail.Customer.Province, time.Now().Format("2006"), n)
	detail.ContractNumber = contractNumber
	detail.Signed = 1
	detail.Status = models.OfflineStatusFinanceCheck
	detail.ActualIncome = req.ActualIncome
	detail.ReceiptNumber = req.ReceiptNumber
	detail.AgreementNumber = req.AgreementNumber
	detail.CompletePay = 1
	err = o.Orm.Updates(&detail).Error
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	// 写入记录表
	record := models.OfflineOrderProgress{}
	record.Creator = teacher.SysUser.Username
	record.Status = models.OfflineStatusFinanceCheck //变更到财务复审状态
	record.OrderId = req.Id
	record.OperateTime = time.Now()
	record.FollowUp = req.FollowUp
	record.Remarks = req.Remarks
	o.Orm.Save(&record)
	// 更新身份证
	if req.IdCard != "" {
		o.Orm.Table(models.SysStudent{}.TableName()).Where("id = ?", detail.BuyerId).UpdateColumn("id_card", req.IdCard)
	}
	// 变更订单状态等信息
	o.OK(nil, "success")
}

func (o Order) Detail(ctx *gin.Context) {
	s := service.Order{}
	req := dto.GetOrderDetailRequest{}
	if err := o.MakeContext(ctx).MakeOrm().MakeService(&s.Service).
		Bind(&req).Errors; err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	order := models.OfflineOrder{}
	err := s.Detail(req.Id, &order)
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
	} else {
		var fileName string
		// 获取模板name
		if len(order.Course) <= 0 {
			o.Error(http.StatusInternalServerError, nil, "订单竟然没有关联课程？？")
			return
		}
		// 获取模版名称
		if order.Course[0].FileId != "" {
			eSign := new(models.ESignContract)
			o.Orm.Where("template_id", order.Course[0].FileId).Find(eSign)
			fileName = eSign.FileName
		}
		rsp := &response.GetOrderDetailResponse{}
		rsp.Make(order)
		rsp.Detail.FileName = fileName
		o.OK(rsp, "success")
	}
}

func (o Order) GetOrderList(ctx *gin.Context) {
	s := service.Order{}
	req := dto.GetOrderListRequest{}
	if err := o.MakeContext(ctx).MakeOrm().MakeService(&s.Service).
		Bind(&req, binding.Default(ctx.Request.Method, ctx.ContentType())).Errors; err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	orders := make([]models.OfflineOrder, 0)
	var count int64
	teacher := o.GetTeacherInfo(ctx)
	err := s.GetOrderList(&orders, &count, req, teacher.SysUser.UserId)
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	rsp := make([]response.GetOrderListResponse, len(orders))
	for k, v := range orders {
		var name string
		var phone string
		courseArr := make([]response.Course, len(v.Course))
		if v.Customer != nil {
			name = v.Customer.Name
			phone = v.Customer.Phone
		}
		for kk, vv := range v.Course {
			courseArr[kk] = response.Course{
				CourseId:     vv.CourseId,
				Cover:        vv.Cover,
				Name:         vv.Name,
				Introduction: vv.Introduction,
			}
		}
		rsp[k] = response.GetOrderListResponse{
			Id:          v.Id,
			Name:        name,
			Phone:       phone,
			Courses:     courseArr,
			CompletePay: v.CompletePay,
		}
	}
	o.PageOK(rsp, int(count), req.GetPageIndex(), req.GetPageSize(), "success")
}

func (o Order) UploadContract(ctx *gin.Context) {
	o.MakeContext(ctx)
	rsp, err := util.Upload(ctx, "file")
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	o.OK(Base64Rsp{Path: rsp.Path}, "success")
}

type Base64Req struct {
	File string `json:"file" binding:"required"`
}
type Base64Rsp struct {
	Path string `json:"path"`
}

func (o Order) UploadBase64(ctx *gin.Context) {
	o.MakeContext(ctx)
	req := Base64Req{}
	if err := ctx.BindJSON(&req); err != nil {
		o.Error(http.StatusBadRequest, err, err.Error())
		return
	}
	rsp, err := util.UploadBase64(ctx, req.File)
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	o.OK(Base64Rsp{Path: rsp.Path}, "success")
}

func (o Order) UpdateContract(ctx *gin.Context) {
	req := dto.OrderBindContractRequest{}
	if err := o.MakeContext(ctx).MakeOrm().
		Bind(&req, binding.JSON).Errors; err != nil {
		o.Error(http.StatusBadRequest, err, err.Error())
		return
	}
	// 获取线下订单
	var obj models.OfflineOrder
	obj.Id = req.Id
	db, err := o.GetOrm()
	if err != nil {
		xlog.Error(err)
		o.Error(http.StatusInternalServerError, err, "服务器异常")
		return
	}
	err = db.Preload("Customer").Find(&obj).Error
	if err != nil {
		xlog.Error(err)
		o.Error(http.StatusInternalServerError, nil, "服务器异常")
		return
	}
	if obj.Customer == nil || obj.Customer.Id == 0 {
		o.Error(http.StatusInternalServerError, nil, "该订单异常")
		return
	}
	if obj.Customer.Province == 0 {
		o.Error(http.StatusInternalServerError, nil, "该学生尚未绑定省份")
		return
	}
	// 更新订单合同等信息
	err = db.Table(obj.TableName()).Where("id = ?", obj.Id).Updates(map[string]interface{}{
		"contract_url": req.Url,
	}).Error
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	o.OK(nil, "success")
}

func (o Order) GetCreateTemplateUrl(ctx *gin.Context) {
	req := dto2.GetCreateTemplateUrl{}
	err := o.MakeContext(ctx).Bind(&req, binding.Default(ctx.Request.Method, ctx.ContentType())).Errors
	if err != nil {
		o.Error(http.StatusBadRequest, err, err.Error())
		return
	}
	var jsonStr string
	if data, err := json.Marshal(req); err == nil {
		jsonStr = string(data)
	}
	//sign_service.EsignInitService()
	r, status := HttpHelper.SendCommHttp("/v3/doc-templates/doc-template-create-url", jsonStr, http.MethodPost)
	if status != 200 {
		o.Error(http.StatusInternalServerError, nil, "请求e电签接口错误")
		return
	}
	rsp := Beans.GetCreateTemplateUrlRsp{}
	json.Unmarshal(r, &rsp)
	if rsp.Code != 0 {
		o.Error(http.StatusInternalServerError, nil, rsp.Message)
		return
	}
	// 获取原始上传文件名
	eSignContract := new(models.ESignContract)
	err = o.Orm.Model(eSignContract).Where("file_id = ?", req.FileId).Find(eSignContract).Error
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	rsp.Data.DocTemplateName = eSignContract.FileName
	o.OK(rsp.Data, rsp.Message)

}

func (o Order) FillTemplate(ctx *gin.Context) {
	req := Beans.FillTemplateRequest{}
	err := o.MakeContext(ctx).MakeOrm().Bind(&req, binding.JSON).Errors
	if err != nil {
		o.Error(http.StatusBadRequest, err, err.Error())
		return
	}
	o.Orm.Model(models.OfflineOrder{}).Where("id = ?", req.Id).Updates(map[string]interface{}{"signed": 0, "sign_flow_id": ""})
	rsp, err := HttpHelper.FillTemplate(req)
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	if rsp.Code != 0 {
		o.Error(http.StatusInternalServerError, nil, rsp.Message)
		return
	}
	o.OK(rsp.Data, rsp.Message)
}

func (o Order) GetTemplateDetail(ctx *gin.Context) {
	req := dto2.GetTemplateDetail{}
	err := o.MakeContext(ctx).MakeOrm().Bind(&req, binding.Default(ctx.Request.Method, ctx.ContentType())).Errors
	if err != nil {
		o.Error(http.StatusBadRequest, err, err.Error())
		return
	}
	rsp, err := HttpHelper.GetTemplateDetail(req.DocTemplateId)
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	if rsp.Code != 0 {
		o.Error(http.StatusInternalServerError, err, rsp.Message)
		return
	}
	o.OK(rsp.Data, rsp.Message)
}

type bindFileId struct {
	FileId string `json:"file_id"`
	Id     int    `json:"id"`
}

func (o Order) BindFileId(ctx *gin.Context) {
	o.MakeContext(ctx).MakeOrm()
	req := bindFileId{}
	err := o.MakeContext(ctx).MakeOrm().Bind(&req, binding.JSON).Errors
	if err != nil {
		o.Error(http.StatusBadRequest, err, err.Error())
		return
	}
	var obj models.OfflineOrder
	err = o.Orm.Preload("Customer").Where("id = ?", req.Id).Find(&obj).Error
	if err != nil {
		xlog.Error(err)
		o.Error(http.StatusInternalServerError, nil, "服务器异常")
		return
	}
	if obj.Customer == nil || obj.Customer.Id == 0 {
		o.Error(http.StatusInternalServerError, nil, "该订单异常")
		return
	}
	if obj.Customer.Province == 0 {
		o.Error(http.StatusInternalServerError, nil, "您暂为绑定省份,请先完善基础信息")
		return
	}
	//n, err := models.Contract{}.GetMaxContractNumAndInsert(o.Orm, obj.Customer.Province, time.Now().Format("2006"))
	//
	err = o.Orm.Model(models.OfflineOrder{}).Where("id = ?", req.Id).Update("file_id", req.FileId).Error
	if err != nil {
		o.Error(http.StatusInternalServerError, err, err.Error())
		return
	}

	o.OK(nil, "success")
}
